package com.googlecode.lohr.parser.combinators;


import java.util.Arrays;

import com.googlecode.lohr.parser.combinators.matcher.AnyStringMatcher;
import com.googlecode.lohr.parser.combinators.matcher.ChoiceMatcher;
import com.googlecode.lohr.parser.combinators.matcher.ExcludingMatcher;
import com.googlecode.lohr.parser.combinators.matcher.LongestMatcher;
import com.googlecode.lohr.parser.combinators.matcher.Matcher;
import com.googlecode.lohr.parser.combinators.matcher.RangeMatcher;
import com.googlecode.lohr.parser.combinators.matcher.RepetitionMatcher;
import com.googlecode.lohr.parser.combinators.matcher.SequenceMatcher;
import com.googlecode.lohr.parser.combinators.matcher.StringMatcher;

public final class Parsers
{
	public static final int max= Integer.MAX_VALUE;
	
	private Parsers()
	{
		throw new UnsupportedOperationException("Utility class");
	}

	public static StringMatcher string(final String string)
	{
		return new StringMatcher(string);
	}
	public static StringMatcher str(final String string)
	{
		return new StringMatcher(string);
	}
	public static StringMatcher string(final char c)
	{
		return new StringMatcher(""+c);
	}
	public static StringMatcher str(final char c)
	{
		return new StringMatcher(""+c);
	}

	public static Matcher range(final char from, final char to)
	{
		return new RangeMatcher(to, from);
	}

	public static Matcher sequence(final Matcher... matchers)
	{
		return new SequenceMatcher(matchers);
	}
	public static Matcher seq(final Matcher... matchers)
	{
		return new SequenceMatcher(matchers);
	}

	public static ChoiceMatcher choice(final Matcher... matchers)
	{
		return new ChoiceMatcher(matchers);
	}
	public static ChoiceMatcher cho(final Matcher... matchers)
	{
		return new ChoiceMatcher(matchers);
	}
	public static ChoiceMatcher lchoice(final Matcher... matchers)
	{
		return new LongestMatcher(new ChoiceMatcher(matchers));
	}
	public static ChoiceMatcher lcho(final Matcher... matchers)
	{
		return new LongestMatcher(new ChoiceMatcher(matchers));
	}
	
	public static Matcher longest(final Matcher... matchers)
	{
		return new LongestMatcher(matchers);
	}
	public static Matcher lng(final Matcher... matchers)
	{
		return new LongestMatcher(matchers);
	}
	
	public static Matcher anyChar()
	{
		return new AnyStringMatcher(1);
	}
	
	public static Matcher excluding(final Matcher matcher, final Matcher... filters)
	{
		return new ExcludingMatcher(matcher, filters);
	}
	public static Matcher exc(final Matcher matcher, final Matcher... filters)
	{
		return new ExcludingMatcher(matcher, filters);
	}

	public static Matcher repeat(final int min, final int max, final Matcher matcher)
	{
		return new RepetitionMatcher(min, max, RepetitionMatcher.Type.SEQUENCE, matcher);
	}
	public static Matcher rep(final int min, final int max, final Matcher matcher)
	{
		return new RepetitionMatcher(min, max, RepetitionMatcher.Type.SEQUENCE, matcher);
	}
	public static Matcher rep(final Matcher matcher)
	{
		return new RepetitionMatcher(0, max, RepetitionMatcher.Type.SEQUENCE, matcher);
	}
	public static Matcher lrepeat(final int min, final int max, final Matcher matcher)
	{
		return new LongestMatcher(new RepetitionMatcher(min, max, RepetitionMatcher.Type.SEQUENCE, matcher));
	}
	public static Matcher lrep(final int min, final int max, final Matcher matcher)
	{
		return new LongestMatcher(new RepetitionMatcher(min, max, RepetitionMatcher.Type.SEQUENCE, matcher));
	}
	public static Matcher lrep(final Matcher matcher)
	{
		return new LongestMatcher(new RepetitionMatcher(0, max, RepetitionMatcher.Type.SEQUENCE, matcher));
	}

	// ============================================================================================
	// === OPTIONAL MATCHERS
	// ============================================================================================

	public static Matcher optional(final Matcher matcher)
	{
		return choice(matcher, string(""));
	}
	public static Matcher opt(final Matcher matcher)
	{
		return choice(matcher, string(""));
	}

	public static <T> Matcher[] tail(final Matcher[] array)
	{
		return Arrays.asList(array).subList(1, array.length).toArray(new Matcher[] {});
	}
}
